/*
//              INTEL CORPORATION PROPRIETARY INFORMATION
//  This software is supplied under the terms of a license  agreement or
//  nondisclosure agreement with Intel Corporation and may not be copied
//  or disclosed except in  accordance  with the terms of that agreement.
//    Copyright (c) 2006-2007 Intel Corporation. All Rights Reserved.
//
*/
#include "umc_defs.h"
#if defined (UMC_ENABLE_DVHD_VIDEO_ENCODER)

#include "umc_dv100_enc_1080_50i_segment_reader.h"

namespace UMC
{

DV100_1080_50i_SegmentReader::DV100_1080_50i_SegmentReader(void)
{
}

DV100_1080_50i_SegmentReader::~DV100_1080_50i_SegmentReader(void)
{
}

static const Ipp32s MBLumaWidth = 16;
static const Ipp32s MBChromaWidth = 8;
static const Ipp32s MBHeight = 16;
static const Ipp32s MBHalfHeight = 8;
static const Ipp32s SBLumaWidth = 9 * MBLumaWidth;
static const Ipp32s SBChromaWidth = 9 * MBChromaWidth;

static
void InitOffsets(size_t *YOffsets, size_t *UOffsets, size_t *VOffsets,
                 const size_t lPitches[], Ipp16s nDIFSeqNum, Ipp16s nVideoSegmentNum)
{
    Ipp32s MBNum;
    Ipp32s nChannelNum = nDIFSeqNum/12;
    nDIFSeqNum %= 12;

    size_t YPitch = lPitches[0];
    size_t UPitch = lPitches[1];
    size_t VPitch = lPitches[2];

    if(nDIFSeqNum < 11)
    {
        //Main Unit
        Ipp32s i = (nVideoSegmentNum + 27*nDIFSeqNum) % 11;
        Ipp32s k = (nVideoSegmentNum + 27*nDIFSeqNum) / 11;
        Ipp32s h = nChannelNum;
        Ipp32s SuperBlockVertOrder[]=
        {
            (4*h + i + 2) % 11,
            (4*h + i + 6) % 11,
            (4*h + i + 8) % 11,
            (4*h + i + 0) % 11,
            (4*h + i + 4) % 11
        };
        Ipp32s SuperBlockHorzOrder[] = {2, 1, 3, 0, 4};
        Ipp32s Row = k/9;
        Ipp32s Col = k%9;

        for(MBNum=0; MBNum<5; MBNum++)
        {
            YOffsets[2*MBNum] = MBHeight * YPitch + //Skip A0
                               (h/2 + SuperBlockVertOrder[MBNum]*6 + Row*2) * MBHeight * YPitch +
                               ((h%2 + SuperBlockHorzOrder[MBNum]*2 ) * SBLumaWidth + Col * MBLumaWidth );
            YOffsets[2*MBNum+1] = YOffsets[2*MBNum] + MBHalfHeight * YPitch;

            UOffsets[2*MBNum] = MBHeight * UPitch + //Skip A0
                               (h/2 + SuperBlockVertOrder[MBNum]*6 + Row*2) * MBHeight * UPitch +
                               ((h%2 + SuperBlockHorzOrder[MBNum]*2 ) * SBChromaWidth + Col * MBChromaWidth );
            UOffsets[2*MBNum+1] = UOffsets[2*MBNum] + MBHalfHeight * UPitch;

            VOffsets[2*MBNum] = MBHeight * VPitch + //Skip A0
                               (h/2 + SuperBlockVertOrder[MBNum]*6 + Row*2) * MBHeight * VPitch +
                               ((h%2 + SuperBlockHorzOrder[MBNum]*2 ) * SBChromaWidth + Col * MBChromaWidth );
            VOffsets[2*MBNum+1] = VOffsets[2*MBNum] + MBHalfHeight * VPitch;
        }
    }
    else
    {
        //Edge unit
        for(MBNum=0; MBNum<5; MBNum++)
        {
            if( (nVideoSegmentNum + MBNum*27) < 90)
            {
                //Macro block is from A0

                YOffsets[2*MBNum] = (nVideoSegmentNum + MBNum*27)*MBLumaWidth;
                YOffsets[2*MBNum+1] = YOffsets[2*MBNum] + MBHalfHeight * YPitch;

                UOffsets[2*MBNum] = (nVideoSegmentNum + MBNum*27)*MBChromaWidth;
                UOffsets[2*MBNum+1] = UOffsets[2*MBNum] + MBHalfHeight * UPitch;

                VOffsets[2*MBNum] = (nVideoSegmentNum + MBNum*27)*MBChromaWidth;
                VOffsets[2*MBNum+1] = VOffsets[2*MBNum] + MBHalfHeight * VPitch;
            }
            else
            {
                //Macro block is from A1

                YOffsets[2*MBNum] =  67 * MBHeight * YPitch + //Skip A0 and main unit
                                   ((nVideoSegmentNum + MBNum*27) - 90) * 32;
                YOffsets[2*MBNum+1] = YOffsets[2*MBNum] + MBLumaWidth;

                UOffsets[2*MBNum] =  67 * MBHeight * UPitch + //Skip A0 and main unit
                                   ((nVideoSegmentNum + MBNum*27) - 90) * 16;
                UOffsets[2*MBNum+1] = UOffsets[2*MBNum] + MBChromaWidth;

                VOffsets[2*MBNum] =  67 * MBHeight * VPitch + //Skip A0 and main unit
                                   ((nVideoSegmentNum + MBNum*27) - 90) * 16;
                VOffsets[2*MBNum+1] = VOffsets[2*MBNum] + MBChromaWidth;
            }
        }
    }
}

void DV100_1080_50i_SegmentReader::ReadSegment(struct V_SEGMENT *lpVSegment, Ipp16s DIFSeqOrder, Ipp16s VSegmentOrder)
{
    size_t YOffsets[10], UOffsets[10], VOffsets[10];
    size_t Pitches[3];
    Pitches[0] = m_lpSourceFrame->GetPlanePitch(0);
    Pitches[1] = m_lpSourceFrame->GetPlanePitch(1);
    Pitches[2] = m_lpSourceFrame->GetPlanePitch(2);

    InitOffsets(YOffsets, UOffsets, VOffsets, Pitches, DIFSeqOrder, VSegmentOrder);

    ReadMacroBlocks(YOffsets, UOffsets, VOffsets, lpVSegment, m_lpSourceFrame);
}


}//namespace UMC

#endif // (UMC_ENABLE_DVHD_VIDEO_ENCODER)
